import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch

# 设置中文字体
plt.rcParams.update({
    'font.size': 10,          # 全局字体大小
    'axes.titlesize': 12,     # 标题字体大小
    'axes.labelsize': 10,     # 坐标轴标签字体大小
    'xtick.labelsize': 10,    # x轴刻度字体
    'ytick.labelsize': 10,    # y轴刻度字体
    'legend.fontsize': 10     # 图例字体
})
# 初始化设置
plt.rcParams['font.sans-serif'] = ['KaiTi']  # 中文字体
plt.rcParams['mathtext.fontset'] = 'stix'     # 数学字体
plt.rcParams['axes.unicode_minus'] = False


# 定义凸函数 f(x) = x^2
def convex_function(x):
    return x ** 2

# 生成数据
x = np.linspace(-5, 5, 400)
y = convex_function(x)

# 选择两个点 x1 和 x2
x1, x2 = -3, 3
y1, y2 = convex_function(x1), convex_function(x2)

# 选择 theta 值
theta = 0.4
x_theta = theta * x1 + (1 - theta) * x2
y_theta = convex_function(x_theta)
y_line = theta * y1 + (1 - theta) * y2

# 创建图形
plt.figure(figsize=(10, 6))
ax = plt.gca()

# 绘制函数曲线
plt.plot(x, y, 'b-', linewidth=2, label=r'凸函数 $f(x) = x^2$')

# 绘制两点间的连线
plt.plot([x1, x2], [y1, y2], 'r--', linewidth=1.5, label=r'两点连线 $\theta f(x_1) + (1-\theta)f(x_2)$')

# 绘制线性组合点
plt.plot(x_theta, y_theta, 'go', markersize=8, label=r'$f(\theta x_1 + (1-\theta)x_2)$')
plt.plot(x_theta, y_line, 'ro', markersize=8, label=r'$\theta f(x_1) + (1-\theta)f(x_2)$')

# 连接函数曲线上的点和连线上的点
plt.plot([x_theta, x_theta], [y_theta, y_line], 'k--', linewidth=1, alpha=0.7)

# 标记 x1 和 x2
plt.plot(x1, y1, 'bo', markersize=8)
plt.plot(x2, y2, 'bo', markersize=8)
plt.text(x1, y1 + 0.5, r'$x_1, f(x_1)$', fontsize=12, ha='center')
plt.text(x2, y2 + 0.5, r'$x_2, f(x_2)$', fontsize=12, ha='center')

# 添加注释
plt.text(x_theta + 0.3, y_theta - 0.5,
         r'$f(\theta x_1 + (1-\theta)x_2)$',
         fontsize=12, bbox=dict(facecolor='white', alpha=0.8))
plt.text(x_theta + 0.3, y_line + 0.5,
         r'$\theta f(x_1) + (1-\theta)f(x_2)$',
         fontsize=12, bbox=dict(facecolor='white', alpha=0.8))
plt.text((x1 + x2)/2, max(y1, y2) + 2,
         r'$f(\theta x_1 + (1-\theta)x_2) \leq \theta f(x_1) + (1-\theta)f(x_2)$',
         fontsize=14, fontweight='bold', color='blue')

# 绘制坐标轴
plt.axhline(y=0, color='k', linestyle='-', alpha=0.3)
plt.axvline(x=0, color='k', linestyle='-', alpha=0.3)

# 设置图形属性
plt.grid(True, alpha=0.3)
plt.xlabel('x', fontsize=14)
plt.ylabel('f(x)', fontsize=14)
plt.title('凸函数定义', fontsize=16, fontweight='bold')
plt.axis([-5, 5, -1, 15])
plt.legend(loc='upper left')

# 显示图形
plt.tight_layout()
plt.show()